#!/usr/bin/python
# -*- coding: utf-8 -*-
import omencore
import sys

class MyTestClass(object):
    def __init__(self):
        self.ooo = "azerty"
    def method1(self):
        print "method1"
    def method2(self):
        print "method2"

class MyTestDecorator(omencore.Decorator):
    aaaa = "azerty"
    def method3(self):
        print 'method3'
    def method4(self):
        print 'method4'

def test_decorator():
    test = MyTestDecorator(MyTestClass())
    assert hasattr(test, "method1")
    assert hasattr(test, "method2")
    assert hasattr(test, "method3")
    assert hasattr(test, "method4")
    assert hasattr(test, "aaaa")
    assert hasattr(test, "ooo")
    
    
class OOO(object):
    def method1(self):
        pass
    def method2(self):
        pass

class Myclass(OOO):
    def __init__(self):
        OOO.__init__(self)
    def method1(self):
        print "method1"
    def method2(self):
        print "method2"
        
class Mydecorator(omencore.Decorator):
    def method3(self):
        print 'method3'
    def method4(self):
        print 'method4'

def testMydecorator():
    """Test decorator"""
    
    #create the decorator
    o_decorator = Mydecorator(Myclass())
    
    # check the object implements all methods
    assert hasattr(o_decorator, "method1")
    assert hasattr(o_decorator, "method2")
    assert hasattr(o_decorator, "method3")
    assert hasattr(o_decorator, "method4")
    
    # the object is instance of Mydecorator, Myclass, 
    assert isinstance(o_decorator, Mydecorator)
    assert isinstance(o_decorator, omencore.Decorator)
    
    
# The simplest way to create a singleton is to use the singleton pattern
# defined by the singleton decorator


####################### Singleton unit test ############################
@omencore.singleton
class TestSingletonClass(object):
    def __init__(self):
        self.__string = ''    
    def set_string(self, a_string):
        self.__string = a_string        
    def get_string(self):
        return self.__string

def test_creation():
    """TestSingleton: creation test"""
    oo1 = TestSingletonClass()
    oo2 = TestSingletonClass()
    oo3 = TestSingletonClass()        
    assert oo1 == oo2
    assert oo1 == oo3
    assert oo3 == oo2

def test_set_and_get():
    """TestSingleton: creation test"""
    oo1 = TestSingletonClass()
    oo2 = TestSingletonClass()
    oo3 = TestSingletonClass()
    oo1.set_string("oo1")
    oo2.set_string("oo2")
    oo3.set_string("oo3")
    assert oo1.get_string() == oo2.get_string()
    assert oo1.get_string() == oo3.get_string()
    assert oo3.get_string() == oo2.get_string()


# Subclassing a singleton is not often used.
# You can find many sample in python on the internet.
# Most of them are very complicated and, I think, not very usefull.

# I propose this simple and not error prone solution
# . create a classic base class containing your code
# . create a singleton class using the "singleton" decorator

# the base class
class MyBaseClass(object):
    def get_string(self):
        return "MyBaseClass"

# the base singleton 
@omencore.singleton
class MySingleton(MyBaseClass):
    pass

# the subclassing singleton
@omencore.singleton
class MyChildSingleton(MyBaseClass):
    def get_string(self):
        return MyBaseClass.get_string(self) + " + MyChildClass"
    
# you can even use multi-inheritance
class MyBaseClass2(object):
    def get_string(self):
        return "MyBaseClass2"

@omencore.singleton  
class MyMultiInheritanceSingleton(MyBaseClass, MyBaseClass2):
    def get_string(self):
        return MyBaseClass.get_string(self) + " + " + MyBaseClass2.get_string(self)

def test_creation_singleton():
    """TestSingleton2: base singleton"""
    oo1 = MySingleton()
    oo2 = MySingleton()
    oo3 = MySingleton()        
    assert oo1 == oo2
    assert oo1 == oo3
    assert oo3 == oo2
    
def test_inherited():
    """TestSingleton: inherited singleton"""
    oo1 = MyChildSingleton()
    oo2 = MyChildSingleton()
    oo3 = MyChildSingleton()        
    assert oo1 == oo2
    assert oo1 == oo3
    assert oo3 == oo2
    assert oo1.get_string() == "MyBaseClass + MyChildClass"
    
def test_multi_inheritance():
    """TestSingleton: multi inherited singleton"""
    oo1 = MyMultiInheritanceSingleton()
    oo2 = MyMultiInheritanceSingleton()
    oo3 = MyMultiInheritanceSingleton()        
    assert oo1 == oo2
    assert oo1 == oo3
    assert oo3 == oo2
    assert oo1.get_string() == "MyBaseClass + MyBaseClass2"



# test the factories
def test_factory():
    omencore.ModuleTools.add_module_folder(sys.argv[0])
    factory = omencore.ClassFactory
    a_object = factory.get_object_by_name('test_classes', 'MyClass1', {})
    from test_core.modules.test_classes import MyClass1
    assert isinstance(a_object, MyClass1)
    a_object = factory.get_object_by_name('test_classes', 'MyClass2', {})
    from test_core.modules.test_classes import MyClass2
    assert isinstance(a_object, MyClass2)
    
